package com.cleaningcloud.cld.service.impl.mini;

import com.cleaningcloud.cld.api.domain.CldStaff;
import com.cleaningcloud.cld.api.domain.Vo.CldStaffDto;
import com.cleaningcloud.cld.domain.*;
import com.cleaningcloud.cld.domain.dto.CldAttendanceDto;
import com.cleaningcloud.cld.domain.mini.UserInfo;
import com.cleaningcloud.cld.domain.mini.addSurveryDto;
import com.cleaningcloud.cld.domain.vo.CldAttendanceVo;
import com.cleaningcloud.cld.domain.vo.CldNoticeConfirmVo;
import com.cleaningcloud.cld.domain.vo.CldRecruitPlanVo;
import com.cleaningcloud.cld.domain.vo.CldStaffVo;
import com.cleaningcloud.cld.mapper.*;
import com.cleaningcloud.cld.mapper.mini.MiniPersonnelMapper;
import com.cleaningcloud.cld.service.PublicCommonService;
import com.cleaningcloud.cld.service.mini.IMiniPersonnelService;
import com.cleaningcloud.common.core.exception.ServiceException;
import com.cleaningcloud.common.core.utils.DateUtils;
import com.cleaningcloud.common.core.utils.StringUtils;
import com.cleaningcloud.common.redis.service.RedisService;
import com.cleaningcloud.common.security.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class MiniPersonnelServiceImpl implements IMiniPersonnelService {

    @Autowired
    private MiniPersonnelMapper miniPersonnelMapper;

    @Autowired
    private CldStaffContractMapper cldStaffContractMapper;

    @Autowired
    private CldNoticeConfirmMapper noticeConfirmMapper;

    @Autowired
    private CldProjectPostMapper cldProjectPostMapper;

    @Autowired
    private CldStaffMapper cldStaffMapper;

    @Autowired
    private CldDegreetitleResultMapper cldDegreetitleResultMapper;

    @Autowired
    private CldAttendanceMapper cldAttendanceMapper;

    @Autowired
    private PublicCommonService publicCommonService;

    @Autowired
    private CldRecruitPlanMapper cldRecruitPlanMapper;

    @Autowired
    private RedisService redisService;

    @Autowired
    private CldRecruitPlanDetailsMapper cldRecruitPlanDetailsMapper;

    @Override
    public UserInfo selectStaffAttributesByStaffId(Long staffId) {
        return miniPersonnelMapper.selectStaffAttributesByStaffId(staffId);
    }

    @Override
    public Map<String, Object> getStaffTodo(Long projectPostId, Long staffId) {
        // 获取当天信息
        LocalDate localDate = LocalDate.now();
        // 获取当前岗位信息
        CldProjectPost cldProjectPost = cldProjectPostMapper.selectCldProjectPostByProjectPostId(projectPostId);

        Map<String, Object> resultMap = miniPersonnelMapper.getStaffTodo(projectPostId, staffId);
        int attTodo = 0;
        // 查询当日考勤数据
        CldAttendanceDto query = new CldAttendanceDto();
        query.setStaffId(SecurityUtils.getUserId());
        query.setAttendanceYear(localDate.getYear());
        query.setAttendanceMonth(localDate.getMonthValue());
        query.setAttendanceDay(localDate.getDayOfMonth());
        List<CldAttendanceVo> cldAttendanceVoList = cldAttendanceMapper.selectCldAttendanceList(query);
        if (!cldAttendanceVoList.isEmpty()) {
            // 获取当前时间时分秒
            LocalTime nowTime = LocalTime.now();
            CldAttendanceVo cldAttendanceVo = cldAttendanceVoList.get(0);
            // 当天无休息
            if (cldAttendanceVo.getIsRest() == 0) {
                // 第一个班次不为空
                if (cldAttendanceVo.getEchoGoToWorkTime1() != null && cldAttendanceVo.getEchoGoOffWorkTime1() != null) {
                    // 当前时间小于上班时间 且 没有打上班卡
                    if (nowTime.isBefore(cldAttendanceVo.getEchoGoToWorkTime1()) && cldAttendanceVo.getGoToWorkTime1() == null) {
                        attTodo = 1;
                    } else if (nowTime.isAfter(cldAttendanceVo.getEchoGoOffWorkTime1()) && cldAttendanceVo.getGoOffWorkTime1() == null) {
                        if (cldAttendanceVo.getEchoGoToWorkTime2() == null) {
                            attTodo = 1;
                        } else {
                            // 当前时间大于下班时间 且 没有打下班卡 且 时间小于第二个班次上班时间
                            if (nowTime.isBefore(cldAttendanceVo.getEchoGoToWorkTime2())) {
                                attTodo = 1;
                            }
                        }
                    }
                }
                // 第二个班次不为空
                if (cldAttendanceVo.getEchoGoToWorkTime2() != null && cldAttendanceVo.getEchoGoOffWorkTime2() != null && attTodo == 0) {
                    // 当前时间小于上班时间 且 没有打上班卡
                    if (nowTime.isBefore(cldAttendanceVo.getEchoGoToWorkTime2()) && cldAttendanceVo.getGoToWorkTime2() == null) {
                        attTodo = 1;
                    } else if (nowTime.isAfter(cldAttendanceVo.getEchoGoOffWorkTime2()) && cldAttendanceVo.getGoOffWorkTime2() == null) {
                        if (cldAttendanceVo.getEchoGoToWorkTime3() == null) {
                            attTodo = 1;
                        } else {
                            // 当前时间大于下班时间 且 没有打下班卡 且 时间小于第三个班次上班时间
                            if (nowTime.isBefore(cldAttendanceVo.getEchoGoToWorkTime3())) {
                                attTodo = 1;
                            }
                        }
                    }
                }
                // 第三个班次不为空
                if (cldAttendanceVo.getEchoGoToWorkTime3() != null && cldAttendanceVo.getEchoGoOffWorkTime3() != null && attTodo == 0) {
                    // 当前时间小于上班时间 且 没有打上班卡
                    if (nowTime.isBefore(cldAttendanceVo.getEchoGoToWorkTime3()) && cldAttendanceVo.getGoToWorkTime3() == null) {
                        attTodo = 1;
                    } else if (nowTime.isAfter(cldAttendanceVo.getEchoGoOffWorkTime3()) && cldAttendanceVo.getGoOffWorkTime3() == null) {
                        attTodo = 1;
                    }
                }
            }
            // 当日存在加班
            if ((cldAttendanceVo.getIsInThisProject() == 1 || cldAttendanceVo.getIsOutExtProject() == 1) && attTodo == 0) {
                // 当前时间小于上班时间 且 没有打上班卡
                if (nowTime.isBefore(LocalTime.from(cldAttendanceVo.getEchoGoToWorkTimeOvertime())) && (cldAttendanceVo.getThisStartTime() == null && cldAttendanceVo.getExtStartTime() == null)) {
                    attTodo = 1;
                } else if (nowTime.isAfter(LocalTime.from(cldAttendanceVo.getEchoGoOffWorkTimeOvertime())) && (cldAttendanceVo.getThisEndTime() == null && cldAttendanceVo.getExtEndTime() == null)) {
                    attTodo = 1;
                }
            }
        }
        resultMap.put("attTodo", attTodo);

        // 补卡申请
        resultMap.put("replaceTodo", miniPersonnelMapper.getReplaceTodo(projectPostId, cldProjectPost.getProjectPostName() == 1 ? 1L : 2L));
        // 工作计划
        resultMap.put("workplanTodo", miniPersonnelMapper.getWorkPlanTodo(projectPostId));

        if (cldProjectPost.getProjectPostName() == 1) {
            // 主管 未处理客诉
            resultMap.put("complaintsTodo", miniPersonnelMapper.getComplaintAdminTodo(cldProjectPost.getProjectId(), cldProjectPost.getStaffId()));
            // 主管 未处理工作安排
            resultMap.put("temporaryTodo", miniPersonnelMapper.getTemporaryAdminTodo(cldProjectPost.getProjectId(), cldProjectPost.getStaffId()));
        } else {
            // 领班/员工 未处理客诉
            resultMap.put("complaintsTodo", miniPersonnelMapper.getComplaintTodo(cldProjectPost.getProjectId(), cldProjectPost.getStaffId()));
            // 领班/员工 未处理工作安排
            resultMap.put("temporaryTodo", miniPersonnelMapper.getTemporaryTodo(cldProjectPost.getProjectId(), cldProjectPost.getStaffId()));
        }
        return resultMap;
    }

    @Override
    public int insertStaff(CldStaffDto cldStaff) {
        cldStaff.setCreateTime(DateUtils.getNowDate());
        cldStaff.setStaffStatus(0);
        cldStaff.setRegisterTime(DateUtils.getNowDate());
        cldStaff.setStaffPassword(SecurityUtils.encryptPassword(StringUtils.isNotEmpty(cldStaff.getStaffPassword()) ? cldStaff.getStaffPassword() : "123456"));
        cldStaff.setStaffNo(String.valueOf(cldStaffMapper.selectStaffCount() + 1));
        cldStaffMapper.insertCldStaff(cldStaff);
        if (StringUtils.isNotEmpty(cldStaff.getReferrerPhone())) {
            CldRecruitPlanVo cldRecruitPlan = cldRecruitPlanMapper.selectCldRecruitPlanByRecruitPhone(cldStaff.getReferrerPhone());
            if (cldRecruitPlan == null) {
                throw new ServiceException("招聘计划查询失败！");
            }
            cldStaff.setRecommenStaffId(cldRecruitPlan.getRecruitLeadingId());
            // 插入招聘员工记录
            CldRecruitPlanDetails cldRecruitPlanDetails = new CldRecruitPlanDetails();
            cldRecruitPlanDetails.setStaffId(cldStaff.getStaffId());
            cldRecruitPlanDetails.setRecruitPlanId(cldRecruitPlan.getRecruitPlanId());
            cldRecruitPlanDetails.setRecruitTime(DateUtils.getNowDate());
            cldRecruitPlanDetails.setStatus(0L);
            cldRecruitPlanDetailsMapper.insertCldRecruitPlanDetails(cldRecruitPlanDetails);
            // 招聘人数满了则修改为已结束
            if ((cldRecruitPlan.getActualNumber() + 1) >= cldRecruitPlan.getRecruitPlanNumber()) {
                cldRecruitPlan.setRecruitPlanStatus(2L);
                cldRecruitPlanMapper.updateCldRecruitPlan(cldRecruitPlan);
            }
        }
        return 1;
    }


    @Override
    public CldStaffVo getStaffInfo(Long staffId) {
        return cldStaffMapper.selectCldStaffByStaffId(staffId);
    }

    @Override
    @Transactional
    public int updateCldStaff(CldStaffDto cldStaff) {
        // 判断是否上传了人事合同信息
        if (cldStaff.getStaffContractId() != null) {
            CldStaffContract cldStaffContract = new CldStaffContract();
            cldStaffContract.setStaffContractId(cldStaff.getStaffContractId());
            cldStaffContract.setAttachment(cldStaff.getStaffContractAttachment());
            cldStaffContractMapper.updateCldStaffContract(cldStaffContract);
        }
        return cldStaffMapper.updateCldStaff(cldStaff);
    }

    @Override
    public int updatePassword(String password, String newPassword) {
        CldStaff cldStaff = cldStaffMapper.selectCldStaffByStaffId(SecurityUtils.getUserId());
        if (cldStaff == null) {
            throw new RuntimeException("用户信息查询失败！");
        }
        if (!SecurityUtils.matchesPassword(password, cldStaff.getStaffPassword())) {
            throw new RuntimeException("旧密码输入错误！");
        }
        cldStaff.setStaffPassword(SecurityUtils.encryptPassword(newPassword));
        return cldStaffMapper.updateCldStaff(cldStaff);
    }

    @Override
    public int recoverPassword(String phone, String password, String code) {
        // 校验验证码是否正确
        String newCode = redisService.getCacheObject(phone);
        if (newCode == null) {
            throw new ServiceException("验证码已失效！");
        }
        if (StringUtils.isEmpty(code)) {
            throw new ServiceException("验证码不能为空！");
        }
        if (!code.equals(newCode)) {
            throw new ServiceException("传入的验证码错误！");
        }
        CldStaff cldStaff = cldStaffMapper.selectStaffByStaffPhone(phone);
        if (cldStaff == null) {
            throw new RuntimeException("该手机号尚未注册！");
        }
        cldStaff.setStaffPassword(SecurityUtils.encryptPassword(password));
        return cldStaffMapper.updateCldStaff(cldStaff);
    }

    /**
     * @Author Shaw
     * @Description 获取员工信息(小程序-在职人员列表)
     * @date: 2025-05-28 15:58
     * @param: //TODO
     */
    @Override
    public List<CldStaffVo> getGroupStaffList(CldStaffDto cldStaffDto) {
        return cldStaffMapper.getStaffList(cldStaffDto);
    }

    @Override
    public List<CldStaffVo> getStaffList(CldStaffDto cldStaffDto) {
        return cldStaffMapper.selectCldStaffList(cldStaffDto);
    }

    @Override
    public int staffResignation(CldStaff cldStaff) {
        cldStaff.setResignApprovalStatus(1L);
        cldStaff.setResignAppTime(DateUtils.getNowDate());
        return cldStaffMapper.updateCldStaff(cldStaff);
    }

    @Override
    public int auditStaff(CldStaff cldStaff) {
        // 入职审核通过
        if (cldStaff.getStaffStatus() == 1) {
            cldStaff.setApprovalId(SecurityUtils.getUserId());
            cldStaff.setApprovalTime(DateUtils.getNowDate());
            cldStaff.setEmploymentTime(DateUtils.getNowDate());
        }
        // 离职审核通过
        if (cldStaff.getResignApprovalStatus() != null) {
            cldStaff.setResignApprovalId(SecurityUtils.getUserId());
            cldStaff.setResignApprovalTime(DateUtils.getNowDate());
            CldStaffVo cldStaffVo = cldStaffMapper.selectCldStaffByStaffId(cldStaff.getStaffId());
            // 如离职日期小于等于当天 则立马离职
            if (cldStaff.getResignApprovalStatus() == 3) {
                if (cldStaffVo.getResignTime().compareTo(new Date()) <= 0) {
                    publicCommonService.staffOptions(cldStaffVo.getStaffId(), 1, cldStaffVo.getProjectId(), null);
                }
            }
        }
        return cldStaffMapper.updateCldStaff(cldStaff);
    }

    @Override
    public List<CldNoticeConfirmVo> getNoticeList(CldNoticeConfirm cldNoticeConfirm) {
        return noticeConfirmMapper.selectCldNoticeConfirmList(cldNoticeConfirm);
    }

    @Override
    public int noticeConfirm(CldNoticeConfirm cldNoticeConfirm) {
        cldNoticeConfirm.setIsConfirm(1L);
        cldNoticeConfirm.setConfirmTime(DateUtils.getNowDate());
        return noticeConfirmMapper.updateCldNoticeConfirm(cldNoticeConfirm);
    }

    @Override
    public CldNoticeConfirmVo getNoticeDetails(Long noticeConfirmId) {
        return noticeConfirmMapper.selectCldNoticeConfirmByNoticeConfirmId(noticeConfirmId);
    }

    @Override
    @Transactional
    public int addSurvery(addSurveryDto addSurveryDto) {
        for (CldDegreetitleResult cldDegreetitleResult : addSurveryDto.getList()) {
            cldDegreetitleResult.setPersonId(SecurityUtils.getUserId());
            // 先删除答案
            cldDegreetitleResultMapper.batchDeleteResultByPersonIdProjectIddegId(SecurityUtils.getUserId(), cldDegreetitleResult.getProjectId(),
                    cldDegreetitleResult.getDegreetitleId(), cldDegreetitleResult.getDegreetitleProblemId());

        }
        cldDegreetitleResultMapper.batchInsertCldDegreetitleResult(addSurveryDto.getList());
        return 1;
    }


}
